﻿using System;
using System.Collections.ObjectModel;
using System.Windows.Automation;
using ProdControls.Interfaces;
using ProdControls.UIAPatterns;
using ProdControls.Utility;
using ProdControls.Verification;
using ProdLogging;

namespace ProdControls.Bridges
{
    internal static class SelectionItemBridge
    {
        #region Required

        /// <summary>
        ///   Gets a value that indicates whether an item is selected.
        /// </summary>
        /// <param name="extension"> The extension interface. </param>
        /// <param name="control"> The base ProdUI control </param>
        /// <returns> <c>true</c> if selected, <c>false</c> otherwise </returns>
        public static bool IsSelectedHook(this ISelectionItem extension, BaseProdControl control)
        {
            try
            {
                return UiaGetIsSelected(control);
            }
            catch (InvalidOperationException)
            {
                if (control.UiaElement.Current.ControlType != ControlType.RadioButton)
                    throw new ArgumentException("This method only works with selectable RadioButtons");
                return NativeGetIsSelected(control);
            }
        }

        /// <summary>
        ///   Determines whether the item at the specified index is selected
        /// </summary>
        /// <param name="extension"> The extension. </param>
        /// <param name="control"> The control. </param>
        /// <param name="index"> The index. </param>
        /// <returns> <c>true</c> if its selected; otherwise, <c>false</c> . </returns>
        public static bool IsSelectedHook(this ISelectionItem extension, BaseProdControl control, int index)
        {
            AutomationElement element = SelectionItemPatternHelper.FindItemByIndex(control.UiaElement, index);
            return SelectionItemPatternHelper.IsItemSelected(element);
        }

        /// <summary>
        ///   Determines whether the item with the specified text is selected
        /// </summary>
        /// <param name="extension"> The extension. </param>
        /// <param name="control"> The control. </param>
        /// <param name="index"> The index. </param>
        /// <returns> <c>true</c> if its selected; otherwise, <c>false</c> . </returns>
        public static bool IsSelectedHook(this ISelectionItem extension, BaseProdControl control, string text)
        {
            AutomationElement element = SelectionItemPatternHelper.FindItemByText(control.UiaElement, text);
            return SelectionItemPatternHelper.IsItemSelected(element);
        }

        private static bool NativeGetIsSelected(BaseProdControl control)
        {
            return ProdRadioButtonNative.GetCheckStateNative((IntPtr) control.UiaElement.Current.NativeWindowHandle);
        }

        private static bool UiaGetIsSelected(BaseProdControl control)
        {
            bool retVal = SelectionItemPatternHelper.IsItemSelected(control.UiaElement);
            LogController.ReceiveLogMessage(new LogMessage(retVal.ToString()));
            return retVal;
        }

      

        /// <summary>
        ///   Deselects any selected items and then selects the current element
        /// </summary>
        /// <param name="extension"> The extended interface. </param>
        /// <param name="control"> The UI Automation element </param>
        /// <param name="index"> The zero-based index of the item to select. </param>
        internal static void SelectHook(this ISelectionItem extension, BaseProdControl control, int index)
        {
            try
            {
                UiaSetSelectedIndex(control, index);
            }
            catch (InvalidOperationException)
            {
                NativeSetSelectedIndex(control, index);
            }
        }

        private static void UiaSetSelectedIndex(BaseProdControl control, int index)
        {
            LogController.ReceiveLogMessage(new LogMessage("Selecting " + index));

            AutomationEventVerifier.Register(new EventRegistrationMessage(control,
                                                                          SelectionItemPattern.ElementSelectedEvent));
            AutomationElement indexedItem = SelectionItemPatternHelper.FindItemByIndex(control.UiaElement, index);
            SelectionItemPatternHelper.SelectItem(indexedItem);
        }

        private static void NativeSetSelectedIndex(BaseProdControl control, int index)
        {
            if (control.UiaElement.Current.ControlType == ControlType.ComboBox)
                ProdListBoxNative.AddSelectedItemNative((IntPtr) control.UiaElement.Current.NativeWindowHandle, index);
        }

        /// <summary>
        ///   Deselects any selected items and then selects the current element
        /// </summary>
        /// <param name="extension"> The extended interface. </param>
        /// <param name="control"> The UI Automation element </param>
        /// <param name="text"> The text of the item to select. </param>
        internal static void SelectHook(this ISelectionItem extension, BaseProdControl control, string text)
        {
            try
            {
                UiaSelectItem(control, text);
            }
            catch (InvalidOperationException)
            {
                NativeSelectItem(control, text);
            }
        }

        private static void UiaSelectItem(BaseProdControl control, string itemText)
        {
            LogController.ReceiveLogMessage(new LogMessage("Selecting " + itemText));

            AutomationEventVerifier.Register(new EventRegistrationMessage(control,
                                                                          SelectionItemPattern.ElementSelectedEvent));
            AutomationElement element = SelectionItemPatternHelper.FindItemByText(control.UiaElement, itemText);
            SelectionItemPatternHelper.SelectItem(element);
        }

        private static void NativeSelectItem(BaseProdControl control, string itemText)
        {
            if (control.UiaElement.Current.ControlType == ControlType.ComboBox)
                ProdListBoxNative.SelectItemNative((IntPtr) control.UiaElement.Current.NativeWindowHandle, itemText);
        }

        #endregion Required
    }
}